/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.bookmarksframework.rule
{
	public class RuleParser implements IRuleParser
	{
		protected var matcher:RegExp = new RegExp("(?<==).*?(?=;|$)", "ig");
		
		// TODO: Optimize.
		public function validate(value:*):Boolean
		{
			var r:String = rule as String;
			var v:String = value + "";
			var matched:Array;
			
			if (r && v)
			{
				if (r == "*")
					return true;
				
				matched = r.match(matcher);
				
				for (var i:int = 0; i < matched.length; ++i)
				{
					if (v.search(new RegExp(matched[i] + "$")) != -1)
						return true;
				}
			}
			
			return false;
		}
		
		public function findKey(value:*):*
		{
			var r:String = rule as String;
			var v:String = value + "";
			var matched:Array;
			
			if (r == "*")
				return value;
			else if (!v)
				return null;
			
			matched = r.match(new RegExp("(?<=\\Q" + v + "\\E=).+?(?=;|$)", "g"));
			
			return matched.length ? matched[0] : null; 
		}
		
		public function findValue(value:*):*
		{
			var result:String;
			var r:String = rule as String;
			var v:String = value + "";
			var matched:Array;
			var resultNum:Number;
			
			if (r == "*")
				return value;
			else if (!v)
				return null;
			
			matched = r.match(matcher);
			
			for (var i:int = 0; i < matched.length; ++i)
			{
				if (v.search(new RegExp(matched[i] + "$")) != -1)
				{
					result = r.match(new RegExp("(?<=;|^).?+(?==\\Q" + matched[i] + "\\E)"))[0];
					break;
				}
			}
			
			resultNum = parseInt(result);
			
			return !isNaN(resultNum) ? resultNum : result;
		}
		
		public function substituteValue(key:*, value:*):*
		{
			var re:RegExp = new RegExp("\\(.+\\)");
			var k:String = k + "";
			var v:String = value + "";
			
			if (k == "*")
				return value;
			else if (!k)
				return null;
			
			return re.test(key) ? key.replace(re, value) : key;  
		}
		
		public function findSubstitution(value:*):*
		{
			var result:String;
			var r:String = rule as String;
			var v:String = value + "";
			var matched:Array;
			var resultNum:Number;
			
			if (r == "*")
				return value;
			else if (!v)
				return null;
			
			matched = r.match(matcher);
			
			for (var i:int = 0; i < matched.length; ++i)
			{
				if (v.search(matched[i] + "$") != -1)
				{
					result = v.replace(new RegExp(matched[i]), "$1");
					break;
				}
			}
			
			resultNum = parseInt(result);
			
			return !isNaN(resultNum) ? resultNum : (result || null);
		}
			
		private var _rule:Object;
		
		public function get rule():Object
		{
			return _rule;
		}
		
		public function set rule(value:Object):void
		{
			_rule = value;
		}
		
	}
}